package cn.edu.circulate;

import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 处理循环依赖的方法
 */
public class MainStart {
	public static void main(String[] args) throws Exception {
		// 这两个类处于循环依赖的状态
		List<String> loadClass = new ArrayList<>();
		loadClass.add("cn.edu.circulate.InstanceA");
		loadClass.add("cn.edu.circulate.InstanceB");

		for (String beanName : loadClass) {
			Object bean = getBean(beanName);

			if(bean instanceof InstanceA){
				InstanceA a= (InstanceA) getBean(beanName);
				a.say();
			}
		}

	}

	// 一级缓存 单例池   成熟态Bean
	private static Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	// 二级缓存   纯净态Bean (存储不完整的Bean用于解决循环依赖中多线程读取一级缓存的脏数据)
	// 所以当有了三级缓存后，它还一定要存在，  因为它要存储的 aop创建的动态代理对象,  不可能重复创建
	private static Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(256);

	// 三级缓存
	private static Map<String,ObjectFactory<?>> factoryEarlySingletonObjects = new ConcurrentHashMap<>(256);


	// 标识当前是不是循环依赖   如果正在创建并且从一级缓存中没有拿到是不是说明是依赖
	private static Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	/**
	 * 创建Bean
	 * @param beanName
	 * @return
	 */
	private static Object getBean(String beanName) throws Exception {
		//获取对应的clas内容
		Class<?> beanClass = Class.forName(beanName);

		Object bean = getSingleton(beanName);
		if(bean != null){
			return bean;
		}

		// 开始创建Bean，增加到标志类型,表示当前bean正在被创建
		singletonsCurrentlyInCreation.add(beanName);

		// 1.实例化
		Object beanInstanc = beanClass.newInstance();

		ObjectFactory<?> factory= () -> {
			JdkProxyBeanPostProcessor beanPostProcessor=new JdkProxyBeanPostProcessor();
			return beanPostProcessor.getEarlyBeanReference(beanInstanc,beanName);
		};
		// 把创建bean的动态代理类封装到第三级缓存中,可已直接通过beanName 获取 ObjectFactory 进行调用
		// beanName的代理对象
		factoryEarlySingletonObjects.put(beanName,factory);

		//2.属性赋值
		// 获取所有的属性名
		Field[] declaredFields = beanClass.getDeclaredFields();

		for (Field declaredField : declaredFields) {
			// 从属性上拿到@Autowired
			Autowired annotation = declaredField.getAnnotation(Autowired.class);

			// 说明属性上有@Autowired
			if (annotation != null){
				Class<?> type = declaredField.getType();

				//com.tuling.circulardependencies.InstanceB
				getBean(type.getName());
			}
		}
		// 3.初始化 (省略）
		// 创建动态代理

		// 存入到一级缓存
		singletonObjects.put(beanName,beanInstanc);
		return beanInstanc;
	}


	public static Object getSingleton(String beanName){
		//首先从一级缓存中获取
		Object bean = singletonObjects.get(beanName);
		// 如果一级缓存没有拿到  是不是就说明当前是循环依赖创建
		if(bean==null && singletonsCurrentlyInCreation.contains(beanName)){
			// 调用bean的后置处理器创建动态代理
			bean = earlySingletonObjects.get(beanName);
			if(bean==null){
				// 获取 ObjectFactory 里面是生成动态代理的方法,通过getObject() 生成对应的动态代理
				ObjectFactory<?> factory = factoryEarlySingletonObjects.get(beanName);
				bean = factory.getObject();
			}
		}
		return bean;
	}
}

